package cd.cdyb.sms.service.impl;

import cd.cdyb.sms.dao.SignatureDao;
import cd.cdyb.sms.domain.Signature;
import cd.cdyb.sms.dto.PageResult;
import cd.cdyb.sms.dto.expand.ExSignatureDto;
import cd.cdyb.sms.dto.query.SignatureQueryDto;
import cd.cdyb.sms.exception.BusinessException;
import cd.cdyb.sms.service.SignatureService;
import cd.cdyb.sms.utils.BeanUtilPlus;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Service("signatureService")
public class SignatureServiceImpl implements SignatureService {


    @Resource
    private SignatureDao signatureDao;

    @Resource
    private RestTemplate restTemplate;

    @Value("${sms.url}")
    private String url;

    @Value("${sms.appid}")
    private String appid;

    @Value("${sms.appKey}")
    private String appKey;

    @Override
    public void insertSignature(ExSignatureDto exSignatureDto) throws BusinessException {
        try {
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            String signName = "【" + exSignatureDto.getName() + "】";
            exSignatureDto.setName(signName);
            Map<String, Object> requestParams = createRequestParams(appid, appKey, exSignatureDto);
            HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(requestParams, headers);
            ResponseEntity<JSONObject> responseEntity = restTemplate.postForEntity(url + "/send/SignatureReport", requestEntity, JSONObject.class);
            HttpStatus statusCode = responseEntity.getStatusCode();
            if (statusCode == HttpStatus.OK) {
                JSONObject responseBody = responseEntity.getBody();
                if (Objects.isNull(responseBody)) {
                    throw new BusinessException("签名申请失败，请重试");
                }
                String code = responseBody.getString("code");
                if (!"200".equals(code)) {
                    throw new BusinessException("签名申请失败，请重试");
                }
                Signature signature = new Signature();
                String signatureId = responseBody.getString("signature_id");
                if (StringUtils.isNotBlank(signatureId)) {
                    signature.setName(exSignatureDto.getName());
                    signature.setType(exSignatureDto.getType());
                    signature.setCompanyId(exSignatureDto.getCompanyId());
                    signature.setStatus(1);
                    signature.setNumber(signatureId);
                    signatureDao.insert(signature);
                }
            } else {
                throw new BusinessException("第三方请求失败，请重试");
            }
        } catch (Exception e) {
            throw new BusinessException(e.getMessage());
        }
    }

    @Override
    public PageResult<ExSignatureDto> findSignaturePage(SignatureQueryDto exSignatureDto) {
        Page<Signature> page = new Page<>(exSignatureDto.getPageNo(), exSignatureDto.getPageSize());
        IPage<ExSignatureDto> iPage = signatureDao.findSignatureList(exSignatureDto, page);
        List<ExSignatureDto> signatureList = iPage.getRecords();
        if (!CollectionUtils.isEmpty(signatureList)) {
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            Map<String, Object> requestParams = new HashMap<>();
            requestParams.put("appid", appid);
            requestParams.put("appkey", appKey);
            signatureList.stream().filter(signature -> signature.getStatus() == 1).forEach(signature -> {
                requestParams.put("signature_id", signature.getNumber());
                HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(requestParams, headers);
                ResponseEntity<JSONObject> responseEntity = restTemplate.postForEntity(url + "/send/getUserSignature", requestEntity, JSONObject.class);
                JSONObject body = responseEntity.getBody();
                if (responseEntity.getStatusCode() != HttpStatus.OK || Objects.isNull(body)) {
                    return;
                }
                String code = body.getString("code");
                JSONObject result = body.getJSONObject("result");
                if (!"200".equals(code) || Objects.isNull(result)) {
                    return;
                }
                Integer auditStatus = result.getInteger("audit_status");
                if (Objects.nonNull(auditStatus)) {
                    LambdaUpdateWrapper<Signature> updateWrapper = new LambdaUpdateWrapper<>();
                    updateWrapper.set(Signature::getStatus, auditStatus)
                            .eq(Signature::getSignatureId, signature.getSignatureId());
                    signatureDao.update(null, updateWrapper);
                }
            });
            iPage = signatureDao.findSignatureList(exSignatureDto, page);
        }
        return new PageResult<>(exSignatureDto.getPageNo(), exSignatureDto.getPageSize(), iPage.getRecords(), iPage.getTotal());
    }

    @Override
    public Signature getSignatureById(Integer signatureId) throws BusinessException {
        Signature signature = signatureDao.selectById(signatureId);
        if (Objects.isNull(signature)) {
            throw new BusinessException("签名不存在");
        }
        if (1 == signature.getStatus()) {
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            Map<String, Object> requestParams = new HashMap<>();
            requestParams.put("appid", appid);
            requestParams.put("appkey", appKey);
            requestParams.put("signature_id", signature.getNumber());
            HttpEntity<Map<String, Object>> requestEntity = new HttpEntity<>(requestParams, headers);
            ResponseEntity<JSONObject> responseEntity = restTemplate.postForEntity(url + "/send/getUserSignature", requestEntity, JSONObject.class);
            JSONObject body = responseEntity.getBody();
            if (responseEntity.getStatusCode() == HttpStatus.OK && Objects.nonNull(body)) {
                String code = body.getString("code");
                JSONObject result = body.getJSONObject("result");
                if ("200".equals(code) && Objects.nonNull(result)) {
                    Integer auditStatus = result.getInteger("audit_status");
                    if (Objects.nonNull(auditStatus)) {
                        LambdaUpdateWrapper<Signature> updateWrapper = new LambdaUpdateWrapper<>();
                        updateWrapper.set(Signature::getStatus, auditStatus)
                                .eq(Signature::getSignatureId, signature.getSignatureId());
                        signatureDao.update(null, updateWrapper);
                        signature = signatureDao.selectById(signatureId);
                    }
                }
            }
        }
        return signature;
    }

    @Override
    public Map<String, Long> indexSignatureStatisticsWithClient(Integer companyId) {
        HashMap<String, Long> map = new HashMap<>();
        map.put("wait", 0L);
        map.put("pass", 0L);
        map.put("fail", 0L);
        LambdaQueryWrapper<Signature> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(Signature::getStatus)
                .eq(Signature::getCompanyId, companyId);
        List<Signature> signatureList = signatureDao.selectList(wrapper);
        Map<Integer, Long> statusCountMap = signatureList.stream()
                .collect(Collectors.groupingBy(Signature::getStatus, Collectors.counting()));
        statusCountMap.forEach((status, count) -> {
            if (1 == status) {
                map.put("wait", count);
            }
            if (2 == status) {
                map.put("pass", count);
            }
            if (3 == status) {
                map.put("fail", count);
            }
        });
        return map;
    }

    @Override
    public List<ExSignatureDto> findSignatureList(SignatureQueryDto exSignatureDto) {
        LambdaQueryWrapper<Signature> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Signature::getStatus, 2);
        if (Objects.nonNull(exSignatureDto.getType())) {
            wrapper.eq(Signature::getType, exSignatureDto.getType());
        }
        if (Objects.nonNull(exSignatureDto.getCompanyId())) {
            wrapper.eq(Signature::getCompanyId, exSignatureDto.getCompanyId());
        }
        if (StringUtils.isNotBlank(exSignatureDto.getName())) {
            wrapper.like(Signature::getName, exSignatureDto.getName());
        }
        List<Signature> signatureList = signatureDao.selectList(wrapper);
        return BeanUtilPlus.copyAs(signatureList, ExSignatureDto.class);
    }

    private Map<String, Object> createRequestParams(String appid, String appKey, ExSignatureDto exSignatureDto) {
        Map<String, Object> requestParams = new HashMap<>();
        requestParams.put("appid", appid);
        requestParams.put("appkey", appKey);
        requestParams.put("title", exSignatureDto.getName());
        requestParams.put("type", exSignatureDto.getType());
        return requestParams;
    }
}
